#include <string.h>

#include "board.h"
#include "adc.h"


static struct adc_buf* buffers[NUM_ANALOG_INPUTS];


/** Registers a buffer to be used to store the specified converted channel */
void adc_buf_channel(uint8_t adc_channel, struct adc_buf* s, uint8_t av_nb_sample)
{
    buffers[adc_channel] = s;
    s->av_nb_sample = av_nb_sample;
}


/** Starts conversions */
void adc_init()
{
    memset(buffers, '\0', sizeof(buffers));
}


/* add a new sample value to an adc buffer */
void adc_addvalue(int channel, int value)
{
    uint8_t new_head;
    uint16_t tmpsum;
    struct adc_buf* buf = buffers[channel];
    if (buf) 
    {
        /* update the buffer */    
        new_head = buf->head + 1;
        if (new_head >= buf->av_nb_sample) 
            new_head = 0;
            
        /* tmpsum is used here to prevent buf->sum ever being in 
         * an inconsistent state. This means it can be read at any
         * time from a different thread without thread-safety issues
         * since buf->sum is always written atomically */
        tmpsum = buf->sum;
        tmpsum -= buf->values[new_head];
        buf->values[new_head] = value;
        tmpsum += value;
        buf->sum = tmpsum;
        buf->head = new_head;   
    }
}
